package com.devbobcorn.nekoration.blocks;

import com.devbobcorn.nekoration.NekoConfig;
import com.devbobcorn.nekoration.NekoConfig.VerConnectionDir;
import com.devbobcorn.nekoration.blocks.states.ModStateProperties;
import com.devbobcorn.nekoration.blocks.states.VerticalConnection;

import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.EnumProperty;

public class HalfTimberPillarBlock extends HalfTimberBlock {
    public enum ConnectionType {
        DOUBLE, TRIPLE, PILLAR;
    }

    public static final EnumProperty<VerticalConnection> CONNECTION  = ModStateProperties.VERTICAL_CONNECTION;

    protected void appendProperties(StateManager.Builder<Block, BlockState> s) {
        s.add(COLOR0, COLOR1, CONNECTION);
    }

    public final ConnectionType type;
    public final boolean connectOtherVariant;

    public HalfTimberPillarBlock(Settings settings) {
        super(settings);
        type = ConnectionType.TRIPLE;
        connectOtherVariant = false;
    }

    public HalfTimberPillarBlock(Settings settings, ConnectionType tp, boolean co) {
        super(settings);
        type = tp;
        connectOtherVariant = co;
    }

    public BlockState getPlacementState(ItemPlacementContext ctx) {
        World blockView = ctx.getWorld();
        BlockPos blockPos = ctx.getBlockPos();
        VerConnectionDir config = ctx.getWorld().getGameRules().get(NekoConfig.VER_CONNECTION_DIR).get();
        boolean useBottom = config == VerConnectionDir.BOTTOM2TOP || config == VerConnectionDir.BOTH;
        
        if (config != VerConnectionDir.NEITHER){
            BlockPos blockPosRef = (useBottom) ? blockPos.down() : blockPos.up();
            BlockState stateRef = blockView.getBlockState(blockPosRef);

            boolean connect = stateRef.getBlock() instanceof HalfTimberPillarBlock && (connectOtherVariant || stateRef.getBlock() == this);

            if (!connect && config == VerConnectionDir.BOTH){ // Block below refuses to connect, try the above one
                blockPosRef = blockPos.up();
                stateRef = blockView.getBlockState(blockPosRef);
                connect = stateRef.getBlock() instanceof HalfTimberPillarBlock && (connectOtherVariant || stateRef.getBlock() == this);
                useBottom = false;
            }
            if (connect) {
                if (useBottom){
                    switch (stateRef.get(CONNECTION)) {
                        case S0:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D1);
                        case D0:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D1);
                        case T0:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D1);
                        case D1:
                            return super.getPlacementState(ctx).with(CONNECTION, type == ConnectionType.DOUBLE ? VerticalConnection.S0 : VerticalConnection.T2);
                        case T1:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.T2);
                        case T2:
                            return super.getPlacementState(ctx).with(CONNECTION, type == ConnectionType.PILLAR ? VerticalConnection.T2 : VerticalConnection.S0);
                        default:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.T2);
                    }
                } else {
                    switch (stateRef.get(CONNECTION)) {
                        case S0:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D0);
                        case D1:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D0);
                        case T2:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.D0);
                        case D0:
                            return super.getPlacementState(ctx).with(CONNECTION, type == ConnectionType.DOUBLE ? VerticalConnection.S0 : VerticalConnection.T0);
                        case T1:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.T0);
                        case T0:
                            return super.getPlacementState(ctx).with(CONNECTION, type == ConnectionType.PILLAR ? VerticalConnection.T0 : VerticalConnection.S0);
                        default:
                            return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.T0);
                    }
                }
            }
        }
        return super.getPlacementState(ctx).with(CONNECTION, VerticalConnection.S0);
    }

    public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
        BlockState res = state;
        // TODO HOW THE HELL TO DO THIS
        VerConnectionDir config = (world.getServer() == null) ? VerConnectionDir.BOTTOM2TOP : world.getServer().getGameRules().get(NekoConfig.VER_CONNECTION_DIR).get();
        boolean flag1 = direction == Direction.UP   && (config == VerConnectionDir.BOTTOM2TOP ||  config == VerConnectionDir.BOTH);
        boolean flag2 = direction == Direction.DOWN && (config == VerConnectionDir.TOP2BOTTOM ||  config == VerConnectionDir.BOTH);

        boolean connect = flag1 || flag2;
        if (connect && newState.getBlock() instanceof HalfTimberPillarBlock && (connectOtherVariant || newState.getBlock() == this)) {
            BlockState stateRef;
            if (flag1){ // Block above is ...
                stateRef = world.getBlockState(pos.down()); // Take the block below as an extra reference
                switch (newState.get(CONNECTION)) {
                    case D1:
                        return res.with(CONNECTION, VerticalConnection.D0);
                    case T1:
                        return res.with(CONNECTION, (type == ConnectionType.PILLAR && stateRef.getBlock() instanceof HalfTimberPillarBlock && (connectOtherVariant || stateRef.getBlock() == this)) ? VerticalConnection.T1 : VerticalConnection.T0);
                    case T2:
                        return res.with(CONNECTION, VerticalConnection.T1);
                    default:
                        break;
                }
            } else { // Block below is ...
                stateRef = world.getBlockState(pos.up()); // Take the block above as an extra reference
                switch (newState.get(CONNECTION)) {
                    case D0:
                        return res.with(CONNECTION, VerticalConnection.D1);
                    case T1:
                        return res.with(CONNECTION, (type == ConnectionType.PILLAR && stateRef.getBlock() instanceof HalfTimberPillarBlock && (connectOtherVariant || stateRef.getBlock() == this)) ? VerticalConnection.T1 : VerticalConnection.T2);
                    case T0:
                        return res.with(CONNECTION, VerticalConnection.T1);
                    default:
                        break;
                }
            }
        }
        return res;
    }
}
